package com.dtease.agent.sse.server.util;

import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
* @description 文本分块工具类
* @author chentl
* @class Chunker
* @package com.dtease.agent.sse.server.util
* @since 2025/5/4 08:36
*/
public class Chunker {

    /**
    * @description 混合语义分割与动态窗口
    * @author chentl
    * @class Chunker
    * @package com.dtease.agent.sse.server.util
    * @since 2025/5/14 09:08
    */
    public static List<String> chunkByDeepSeek(String text) {
        List<String> chunks = new ArrayList<>();
        BreakIterator wordIterator = BreakIterator.getWordInstance(Locale.CHINESE);
        wordIterator.setText(text);

        // 最大字符窗口
        int maxWindow = 12;
        int start = wordIterator.first();
        StringBuilder buffer = new StringBuilder(maxWindow);

        for (int end = wordIterator.next(); end != BreakIterator.DONE; end = wordIterator.next()) {
            String word = text.substring(start, end);

            // 混合分割策略
            if (needSplit(buffer, word, maxWindow)) {
                flushBuffer(buffer, chunks);
            }

            // 处理长单词的二次分割
            if (word.length() > maxWindow) {
                chunks.addAll(splitLongWord(word, maxWindow));
            } else {
                buffer.append(word);
            }

            start = end;
        }
        flushBuffer(buffer, chunks);
        return chunks;
    }

    private static boolean needSplit(StringBuilder buffer, String nextWord, int maxWindow) {
        // 动态判断分割点：当前缓冲长度+新词长度超过窗口，或遇到特定边界符
        return (buffer.length() + nextWord.length() > maxWindow) ||
                nextWord.matches("^[.,;:!?\\n]|\\p{P}$");
    }

    private static void flushBuffer(StringBuilder buffer, List<String> chunks) {
        if (buffer.length() > 0) {
            chunks.add(buffer.toString());
            buffer.setLength(0);
        }
    }

    private static List<String> splitLongWord(String word, int maxWindow) {
        List<String> segments = new ArrayList<>();
        int pos = 0;
        while (pos < word.length()) {
            int end = findBestSplitPos(word, pos, Math.min(pos + maxWindow, word.length()));
            segments.add(word.substring(pos, end));
            pos = end;
        }
        return segments;
    }

    private static int findBestSplitPos(String word, int start, int maxEnd) {
        // 优先在非字母数字处分割，其次在子词边界
        for (int i = Math.min(maxEnd, word.length()) - 1; i > start; i--) {
            if (!Character.isLetterOrDigit(word.charAt(i))) return i + 1;
            if (i - start >= 3 && word.substring(i-2, i+1).matches(".*[-_].*")) {
                return i;
            }
        }
        return Math.min(maxEnd, word.length());
    }

    /**
     * 按长度分块
     * @param text 输入文本
     * @param chunkSize 分块大小
     * @return 分块后的文本列表
     */
    public static List<String> chunkByLength(String text, int chunkSize) {
        List<String> chunks = new ArrayList<>();
        for (int i = 0; i < text.length(); i += chunkSize) {
            chunks.add(text.substring(i, Math.min(text.length(), i + chunkSize)));
        }
        return chunks;
    }

    /**
     * 按句子分块
     * @param text 输入文本
     * @return 分块后的文本列表
     */
    public static List<String> chunkBySentence(String text) {
        List<String> chunks = new ArrayList<>();
        BreakIterator iterator = BreakIterator.getSentenceInstance(Locale.CHINESE);
        iterator.setText(text);
        int start = iterator.first();
        for (int end = iterator.next(); end != BreakIterator.DONE; end = iterator.next()) {
            chunks.add(text.substring(start, end));
            start = end;
        }
        return chunks;
    }
}